package rwt.server.railroad;

import org.slf4j.*;

import rwt.server.RailServer;
import rwt.server.core.*;
import rwt.server.mtl.java.MessageTranslationLibrary.DirectionType;
import rwt.server.mtl.java.MessageTranslationLibrary.OnOffType;

public class Train
{
	private static final Logger logger = LoggerFactory.getLogger(Train.class);
	
	public enum ThrottleStatus
	{
		NONE, BASIC_THROTTLE, EMERGENCY_THROTTLE
	}
	
	public static class InitializationData
	{
		IClient client;
		int headSensor;
		int tailSensor;
		
		private InitializationData(IClient client, int headSensor, int tailSensor)
		{
			this.client = client;
			this.headSensor = headSensor;
			this.tailSensor = tailSensor;
		}
	}
	
	private final int trainId;
	private int physicalSlotNum;
	private int virtualAddress;
	private int virtualSlotNum;
	
	private int throttleClientId;
	
	private InitializationData initData;
	private boolean isInitialized = false;
	private ThrottleStatus throttleStatus = ThrottleStatus.NONE;
	
	private int speed;
	private int direction;
	private int light;
	private int horn;
	private int bell;
	private int mute;
	private int throwNextSwitch;
	private int closeNextSwitch;
	
	public Train(int trainId)
	{
		this.trainId = trainId;
	}
	
	public int getTrainId()
	{
		return trainId;
	}
	
	public int getPhysicalSlotNum()
	{
		return physicalSlotNum;
	}
	
	public int getVirtualAddress()
	{
		return virtualAddress;
	}
	
	public int getVirtualSlotNum()
	{
		return virtualSlotNum;
	}
	
	public void setInitialized(int physicalSlotNum, int virtualLocoAddress, int virtualSlotNum)
	{
		this.physicalSlotNum = physicalSlotNum;
		this.virtualAddress = virtualLocoAddress;
		this.virtualSlotNum = virtualSlotNum;
		this.isInitialized = true;
	}
	
	public void clearInitialized()
	{
		this.physicalSlotNum = 0;
		this.virtualAddress = 0;
		this.virtualSlotNum = 0;
		this.initData = null;
		isInitialized = false;
	}
	
	public boolean isInitialized()
	{
		return isInitialized;
	}
	
	public void setInitializationData(IClient initializingClient, int headSensor, int tailSensor)
	{
		this.initData = new InitializationData(initializingClient, headSensor, tailSensor);
	}
	
	public IClient getInitializingClient()
	{
		if (initData == null)
			return null;
		return initData.client;
	}
	
	public int getInitHeadSensor()
	{
		if (initData == null)
			return 0;
		return initData.headSensor;
	}
	
	public int getInitTailSensor()
	{
		if (initData == null)
			return 0;
		return initData.tailSensor;
	}
	
	public void openThrottle(int clientId, ThrottleStatus throttleType)
	{
		if (throttleType == ThrottleStatus.NONE)
		{
			closeThrottle();
			return;
		}
		
		this.throttleStatus = throttleType;
		this.throttleClientId = clientId;
	}
	
	public void closeThrottle()
	{
		if (isEmergency())
			clearInitialized();
		
		this.throttleStatus = ThrottleStatus.NONE;
		this.throttleClientId = 0;
		
		// Reset all variables
		setSpeed(0);
		setDirection(DirectionType.Forward);
		setLight(OnOffType.Off);
		setHorn(OnOffType.Off);
		setBell(OnOffType.Off);
		setMute(OnOffType.Off);
	}
	
	public ThrottleStatus getThrottleStatus()
	{
		return throttleStatus;
	}
	
	public int getThrottleClientId()
	{
		return throttleClientId;
	}
	
//	public void setThrottleStatus(ThrottleStatus throttleStatus)
//	{
//		this.throttleStatus = throttleStatus;
//		logger.info("Throttle status of train " + trainId + " set to " + throttleStatus);
//	}
	
	public int getSpeed()
	{
		return speed;
	}
	
	public void setSpeed(int speed)
	{
		this.speed = speed;
	}
	
	public int getDirection()
	{
		return direction;
	}

	public void setDirection(int direction)
	{
		this.direction = direction;
	}
	
	public int getHorn()
	{
		return horn;
	}
	
	public void setHorn(int horn)
	{
		this.horn = horn;
	}
	
	public int getLight()
	{
		return light;
	}
	
	public void setLight(int light)
	{
		this.light = light;
	}
	
	public int getBell()
	{
		return bell;
	}
	
	public void setBell(int bell)
	{
		this.bell = bell;
	}
	
	public int getMute()
	{
		return mute;
	}
	
	public void setMute(int mute)
	{
		this.mute = mute;
	}

	public int getThrowNextSwitch()
	{
		return throwNextSwitch;
	}

	public void setThrowNextSwitch(int throwNextSwitch)
	{
		this.throwNextSwitch = throwNextSwitch;
	}

	public int getCloseNextSwitch()
	{
		return closeNextSwitch;
	}

	public void setCloseNextSwitch(int closeNextSwitch)
	{
		this.closeNextSwitch = closeNextSwitch;
	}
	
	/**
	 * Returns the user name of the current train operator, or the empty string if the train is not being
	 * operated by any user.
	 */
	public String getOperatorName()
	{
		if (throttleClientId > 0)
		{
			try
			{
				IClient client = RailServer.getClientManager().getClientById(throttleClientId);
				return client.getUser().getUserName();
			}
			catch (KeyNotFoundException e)
			{
				logger.warn("", e);
				return "[Unknown user]";
			}
		}
		
		return "";
	}

	public boolean isEmergency()
	{
		return (getThrottleStatus() == ThrottleStatus.EMERGENCY_THROTTLE);
	}
}
